﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Data.OleDb;
using System.Data;
using MyClass;

namespace GPS_DB
{
    public class SimulationData
    {


        #region Inner variables
        private struct GPSDATA
        {
            public long MiniLon;
            public long MiniLat;
        }
        private ArrayList roadData = new ArrayList();
        private int roadDataIndex;
        private ArrayList testData = new ArrayList();
        private int testDataIndex;
        private int step;
        private bool isStop;
        private bool isManual;
        #endregion

        #region User propertys
        public ArrayList FileNames = new ArrayList();
        public int FileIndex;
        public string RecFileName;

        public int RoadDataNumber
        {
            set { }
            get 
            {
                return roadData.Count;
            }
        }
        public int RoadDataIndex
        {
            set { }
            get
            {
                return roadDataIndex;
            }
        }
        public long CurLon
        {
            set { }
            get
            {
                if (testDataIndex >= testData.Count)
                    return 0;
                GPSDATA tmpD;
                tmpD = (GPSDATA)testData[testDataIndex];
                return tmpD.MiniLon;
            }
        }
        public long CurLat
        {
            set { }
            get
            {

                if (testDataIndex >= testData.Count)
                    return 0;
                GPSDATA tmpD;
                tmpD = (GPSDATA)testData[testDataIndex];
                return tmpD.MiniLat;
            }
        }
        public bool IsStop
        {
            get { return isStop; }
            set { isStop = value; }
        }
        public bool IsManual
        {
            set { isManual = value; }
            get { return isManual; }
        }
        #endregion




        #region User Method
        public SimulationData()
        {
            Clear();
            isStop = false;
        }
        public bool OpenTestFiles()
        {
            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "txt file(*.txt)|*.txt";
            frm1.Title = "Please select simulation data! ";
            frm1.Multiselect = true;
            frm1.InitialDirectory = LrnS.GetItem("StartSimulation");
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("StartSimulation", Path.GetDirectoryName(frm1.FileName));
                if (frm1.FileNames.Length < 1)
                {
                    return false;
                }
                else
                {
                    Clear();
                    foreach (string fn in frm1.FileNames)
                    {
                        FileNames.Add(fn);
                    }
                    return true;
                }
            }
            else
            {
                return false;
            }
        }
        public bool NextTestFile()
        {
            if (FileIndex < FileNames.Count)
            {
                ReadInTestFile((string)FileNames[FileIndex]);
                FileIndex++;
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool NewNextTestPoint()
        {
            GPSDATA d1, d2;

            if (TestDataIsEmpty())
            {
                if (RoadDataIsEmpty())
                {
                    return false;
                }

                d1 = (GPSDATA)roadData[roadDataIndex];
                d2 = (GPSDATA)roadData[roadDataIndex + 1];
                SetDataTestExt( d1.MiniLon,
                                d1.MiniLat,
                                d2.MiniLon,
                                d2.MiniLat);
                roadDataIndex++;
            }
            return true;
        }
        public bool CurrentDataValid()
        {
            GPSDATA tmpD;
            tmpD = (GPSDATA)testData[testDataIndex];
            if ((tmpD.MiniLon != 0) && (tmpD.MiniLat != 0))
                return true;
            else
                return false;
        }
        public void DataPointerInc()
        {
            if (!isStop)
                testDataIndex++;
        }
        public bool IsLineHead()
        {
            if (roadDataIndex == 1 && testDataIndex == 0)
                return true;
            else
                return false;
        }
        public void Clear()
        {
            step = 0;
            testDataIndex = 0;
            testData.Clear();
            roadDataIndex = 0;
            roadData.Clear();
            FileNames.Clear();
            FileIndex = 0;
            RecFileName = DateTime.Now.ToString("yyyyMMddHHmm") + " RecData.txt";
        }
        public void SetRecFileName()
        {
            string filename = "";
            filename = (string)FileNames[FileIndex - 1];
            RecFileName = DateTime.Now.ToString("yyyyMMddHHmm") + " REC" + Path.GetFileNameWithoutExtension(filename) + ".txt";
        }
        public string CurrentSimulationFile()
        {
            return (string)FileNames[FileIndex - 1];
        }
        public void SetTestSec(long lon, long lat)
        {
            int index = 0;
            long dis = long.MaxValue;
            for (int i = 0; i < roadData.Count; i++)
            {
                GPSDATA d=(GPSDATA)roadData[i];
                long tmp = Math.Abs(lon - d.MiniLon * 10) * Math.Abs(lon - d.MiniLon * 10) +
                            Math.Abs(lat - d.MiniLat * 10) * Math.Abs(lat - d.MiniLat * 10);
                if (tmp < dis)
                {
                    dis = tmp;
                    index = i;
                }
            }

            roadDataIndex = index;
            testDataIndex = 0;
            testData.Clear();
        }
        static public void CreatSimulationFile()
        {
            bool ShangXing = false;
            OpenFileDialog frm = new OpenFileDialog();
            frm.Filter = "数据库(.mdb)|*.mdb";
            frm.Title = "请选择数据库文件（不区分上下行）";
            frm.Multiselect = true;
            frm.InitialDirectory = LrnS.GetItem("primarydata");
            if (frm.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("primarydata", Path.GetDirectoryName(frm.FileName));

                foreach (string fn in frm.FileNames)
                {
                    if(fn.Contains("上行"))
                    {
                        if (fn.Contains("下行"))
                        {
                            MessageBox.Show(fn + "\r\n数据文件名称中同时出现上行/下行");
                            continue;
                        }
                        else
                        {
                            ShangXing = true;
                        }
                    }
                    else
                    {
                        if (fn.Contains("下行"))
                        {
                            ShangXing = false;
                        }
                        else
                        {
                            MessageBox.Show(fn + "\r\n数据文件名称中未找到指明上下行的关键字");
                            continue;
                        }
                    }

                    string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fn;
                    OleDbConnection conn = new OleDbConnection(connstr);
                    OleDbDataAdapter dscmd = new OleDbDataAdapter();
                    DataSet resultdataset = new DataSet();

                    string strselect = "";
                    if(ShangXing)
                        strselect = "Select 经度,纬度 From export Order By 序号 Desc";
                    else
                        strselect = "Select 经度,纬度 From export Order By 序号 Asc";
                    
                    OleDbCommand selectcommand = new OleDbCommand(strselect, conn);
                    selectcommand.CommandType = CommandType.Text;

                    try
                    {
                        conn.Open();

                        dscmd.SelectCommand = selectcommand;
                        int numrows = dscmd.Fill(resultdataset, "export");

                        if (numrows > 0)
                        {
                            string path_dir = Application.StartupPath + "\\simulation file\\";
                            if (!Directory.Exists(path_dir))
                                Directory.CreateDirectory(path_dir);
                            string filestr = Path.GetFileNameWithoutExtension(fn);
                            string pathstr = "";
                            if (ShangXing)
                                pathstr = path_dir + filestr + "上行测试" + ".txt";
                            else
                                pathstr = path_dir + filestr + "下行测试" + ".txt";
                            if (File.Exists(pathstr))
                            {
                                File.Delete(pathstr);
                            }
                            using (FileStream fs1 = new FileStream(pathstr, FileMode.Create, FileAccess.ReadWrite))
                            {
                                StreamWriter w1 = new StreamWriter(fs1);

                                int index = 1000;
                                w1.WriteLine((100000 + numrows).ToString().Remove(0, 1));
                                w1.WriteLine("02");
                                for (int i = 0; i < numrows; i++)
                                {
                                    index++;
                                    string lon = resultdataset.Tables["export"].Rows[i]["经度"].ToString();
                                    string lat = resultdataset.Tables["export"].Rows[i]["纬度"].ToString();

                                    string line = "No(" + index.ToString() + ")Sn(测试数据)Sc(" + 
                                                    index.ToString() + ")Sa(017)Mode(101)Lo(";
                                    string str1 = GetGpsStringLonLat(lon, true);
                                    string str2 = GetGpsStringLonLat(lat, false);
                                    bool unvalidpoint = true;
                                    if (((Int64.Parse(str1) > 100000) && (Int64.Parse(str2) > 100000)) || unvalidpoint)
                                    {
                                        line += GetGpsStringLonLat(lon, true) + ")La(" +
                                                GetGpsStringLonLat(lat, false) + ")Tc(00000000)Ns(FFFF)Ss(FFFF)";
                                        line += "NILO(00000)NILA(00000)NOLO(00000)NOLA(00000)SILO(00000)SILA(00000)SOLO(00000)" +
                                                "SOLA(00000)RLon(00000000)RLat(0000000)";
                                        w1.WriteLine(line);
                                    }
                                }

                                w1.Close();
                                fs1.Close();
                            }
                        }
                        else
                        {
                            MessageBox.Show("无可生成的数据！");
                        }
                    }
                    catch (Exception er)
                    {
                        MessageBox.Show(er.Message.ToString());
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
                MessageBox.Show("完成！");
            }
        }
        static public void CreatSimulationFile_xls()
        {
            bool ShangXing = false;
            OpenFileDialog frm = new OpenFileDialog();
            frm.Filter = "数据库(.xlsx)|*.xlsx";
            frm.Title = "请选择数据库文件（不区分上下行）";
            frm.Multiselect = true;
            frm.InitialDirectory = LrnS.GetItem("primarydata_xls");
            if (frm.ShowDialog() != DialogResult.OK)
                return;

            LrnS.SaveItem("primarydata_xls", Path.GetDirectoryName(frm.FileName));
            foreach (string fn in frm.FileNames)
            {
                if (fn.Contains("上行"))
                {
                    if (fn.Contains("下行"))
                    {
                        MessageBox.Show(fn + "\r\n数据文件名称中同时出现上行/下行");
                        continue;
                    }
                    else
                    {
                        ShangXing = true;
                    }
                }
                else
                {
                    if (fn.Contains("下行"))
                    {
                        ShangXing = false;
                    }
                    else
                    {
                        MessageBox.Show(fn + "\r\n数据文件名称中未找到指明上下行的关键字");
                        continue;
                    }
                }

                DataSet ds = null;
                try
                {
                    ds = GF.DsFromExcel(fn);
                    int numrows = ds.Tables["sheet1$"].Rows.Count;

                    if (numrows == 0)
                        MessageBox.Show("无可生成的数据！");
                    
                    string path_dir = Application.StartupPath + "\\simulation file\\";
                    if (!Directory.Exists(path_dir))
                        Directory.CreateDirectory(path_dir);
                    string filestr = Path.GetFileNameWithoutExtension(fn);
                    string pathstr = "";
                    if (ShangXing)
                        pathstr = path_dir + filestr + "上行测试" + ".txt";
                    else
                        pathstr = path_dir + filestr + "下行测试" + ".txt";
                    if (File.Exists(pathstr))
                    {
                        File.Delete(pathstr);
                    }
                    using (FileStream fs1 = new FileStream(pathstr, FileMode.Create, FileAccess.ReadWrite))
                    {
                        StreamWriter w1 = new StreamWriter(fs1);

                        int index = 1000;
                        w1.WriteLine((100000 + numrows).ToString().Remove(0, 1));
                        w1.WriteLine("02");
                        for (int i = 0; i < numrows; i++)
                        {
                            index++;
                            string lon = ds.Tables["sheet1$"].Rows[i][0].ToString().Trim();
                            string lat = ds.Tables["sheet1$"].Rows[i][1].ToString().Trim();

                            string line = "No(" + index.ToString() + ")Sn(测试数据)Sc(" +
                                            index.ToString() + ")Sa(017)Mode(101)Lo(";

                            line += GetGpsStringLonLat(lon, true) + ")La(" +
                                    GetGpsStringLonLat(lat, false) + ")Tc(00000000)Ns(FFFF)Ss(FFFF)";
                            line += "NILO(00000)NILA(00000)NOLO(00000)NOLA(00000)SILO(00000)SILA(00000)SOLO(00000)" +
                                    "SOLA(00000)RLon(00000000)RLat(0000000)";
                            w1.WriteLine(line);

                        }
                        w1.Close();
                        fs1.Close();
                    }

                }
                catch (Exception er)
                {
                    MessageBox.Show(er.Message.ToString());
                }
            }
            MessageBox.Show("完成！");
        }

        static public string GetGpsStringLonLat(string lonlatstr, bool islon)
        {
            lonlatstr = GF.GPSLonLatFormWithoutDos(lonlatstr);
            int intlonlat = int.Parse(lonlatstr);
            intlonlat = intlonlat / 1000000 * 100000 + (intlonlat % 1000000 / 10) * 10 / 6;
            if (islon)
                return intlonlat.ToString().PadLeft(8, '0');
            else
                return intlonlat.ToString().PadLeft(7, '0');

        }
        #endregion



        #region Inner Method
        private bool TestDataIsEmpty()
        {
            if (testDataIndex >= testData.Count)
                return true;
            else
                return false;
        }
        private bool RoadDataIsEmpty()
        {
            if (roadDataIndex >= (roadData.Count - 1))
                return true;
            else
                return false;
        }
        private void ReadInTestFile(string filename)
        {
            roadData.Clear();
            roadDataIndex = 0;
            testData.Clear();
            testDataIndex = 0;
            GPSDATA tempdata = new GPSDATA();
            using (TextReader fs = File.OpenText(filename))
            {
                string readStr = "";

                readStr = fs.ReadLine();//unused
                roadDataIndex = 0;
                readStr = fs.ReadLine();
                step = Int32.Parse(readStr);
                while (true)
                {
                    readStr = fs.ReadLine();
                    if (readStr == null)
                        break;
                    if (readStr.Length > 30)
                    {
                        tempdata.MiniLon = Int64.Parse(readStr.Substring(readStr.IndexOf("Lo(") + 3, 8));
                        tempdata.MiniLat = Int64.Parse(readStr.Substring(readStr.IndexOf("La(") + 3, 7));
                        roadData.Add(tempdata);
                    }
                }
                fs.Close();
            }

        }
        private void SetDataTestExt(long lon1, long lat1, long lon2, long lat2)
        {
            testDataIndex = 0;
            GPSDATA tmpD = new GPSDATA();
            testData.Clear();
            int i, lonStep, latStep;
            if ((lon1 == 0) || (lon2 == 0) || lat1 == 0 || lat2 == 0)
            {
                for (i = 0; i <= step; i++)
                {
                    tmpD.MiniLon = 0;
                    tmpD.MiniLat = 0;
                    testData.Add(tmpD);
                }
            }
            else
            {
                lonStep = (int)(Math.Abs(lon1 - lon2) / step);
                latStep = (int)(Math.Abs(lat1 - lat2) / step);

                for (i = 0; i < step; i++)
                {
                    if (lon1 > lon2)
                        tmpD.MiniLon = lon1 - lonStep * i;
                    else
                        tmpD.MiniLon = lon1 + lonStep * i;
                    if (lat1 > lat2)
                        tmpD.MiniLat = lat1 - latStep * i;
                    else
                        tmpD.MiniLat = lat1 + latStep * i;
                    testData.Add(tmpD);
                }
            }
        }
        #endregion


        /////////////////////////////////////////////////////////////////////////
    }
}
